
class_name SceneMap
extends TileMap




## 指针点击反应
func pointer_callable(_pointer: ScenePointer) -> Dictionary:
	return get_position_all_layer_call(_pointer.position)




## 指针移动
func pointer_move(_pointer: ScenePointer) -> Dictionary:
	return get_position_call_top_info(_pointer.position)




## 获取位置上的最顶层的图块的信息
func get_position_call_top_info(_position: Vector2) -> Dictionary:
	var cell_info: Dictionary = {}
	var cells: Dictionary = get_position_all_layer_call(_position)
	for layer in cells:
		var cell: Dictionary = cells[layer]
		var info: Dictionary = get_tileset_cell_info(cell["tileset"], cell["id"], cell["position"])
		if not info.is_empty():
			cell_info = info
	return cell_info




## 根据传入位置，判断该位置是否为空
func get_position_call_is_empty(_position: Vector2) -> bool:
	var calls_info = get_position_all_layer_call(_position)
	for key in calls_info:
		if calls_info[key]["id"] != -1:
			return true
	
	return false




## 根据传入位置，返回对应图层的对应图块的字典
## 第一个参数是 位置
## 第二个参数如果为 false 就会进行转换变成 map坐标 为 true 则不会转换
func get_position_all_layer_call(_position: Vector2, _is_map_position: bool = false) -> Dictionary:
	var map_position: Vector2 = _position
	if not _is_map_position:
		map_position = local_to_map(_position)
	var result: Dictionary = {}
	for layer in get_layers_count():
		result[get_layer_name(layer)] = {
			# 返回 tileset 编号
			"id": get_cell_alternative_tile(layer, map_position, true),
			# 返回在 tileset 中的位置
			"position": get_cell_atlas_coords(layer, map_position, true),
			"tileset": tile_set,
		}
	
	return result




## 返回 unit 的可移动区域
## 第二个参数决定是否转换结果位置
func get_unit_move_range(_unit: Unit, _transform: bool = false) -> Dictionary:
	var sp = _unit.property.sp
	var map_pos: Vector2i = local_to_map(_unit.position)
	var result: Dictionary = {
		map_pos: 0
	}
	# 获取所有 unit
	var units: Array[Unit] = get_parent().unit_manage.get_all_units()
	var curr: Dictionary = { map_pos: 0 }
	var call: Dictionary = {}
	var new: Dictionary = {}
	for index in range(0, sp):
		call = flood_directions(curr, sp, _unit, units)
		# 合并
		new = {}
		for key in call:
			# 没有就添加
			if not result.has(key):
				new[key] = call[key]
				result[key] = call[key]
			curr = new
	# 转换路径
	if _transform:
		var new_result: Dictionary = {}
		for key in result:
			new_result[map_to_local(key)] = result[key]
		return new_result
	
	return result




## 获取坐标的扩展（相邻）
func flood_directions(_positions: Dictionary, _sp: int, _unit: Unit, _units: Array[Unit]) -> Dictionary:
	var result: Dictionary = {}
	var directions: Array[Vector2i] = [
		Vector2i.UP,
		Vector2i.LEFT,
		Vector2i.DOWN,
		Vector2i.RIGHT
	]
	
	for index in _positions:
		for direction in directions:
			var next: Vector2i = index + direction
			if not get_cell_unti_block(map_to_local(next), _unit, _units):
				continue
			var cost: int = get_cell_cost(next)
			if cost == -1:
				continue
			elif cost <= _sp:
				result[next] = cost + _positions[index]
	
	return result




## 判断 cell 是否可用
## TODO
func is_cell(_map_position: Vector2i) -> Dictionary:
	return {}



## 获取 cell 上是否有 unit 阻挡(敌方单位会进行阻挡)
## 最后一个参数是是否全部都阻挡
func get_cell_unti_block(_local_position: Vector2, _unit: Unit, _units: Array[Unit], _is_all: bool = false) -> bool:
	for unit in _units:
		if unit.position == _local_position:
			# 判断阵营是否相同
			if _unit.get_unit_camp() == unit.get_unit_camp():
				if _is_all:
					return false
				return true
			else:
				return false
	return true




## 获取 cell 的代价
func get_cell_cost(_map_position: Vector2i) -> int:
	var cells: Dictionary = get_position_all_layer_call(_map_position, true)
	var cost: int = -1
	
	for layer in cells:
		var cell: Dictionary = cells[layer]
		var info: Dictionary = get_tileset_cell_info(cell["tileset"], cell["id"], cell["position"])
		if info.is_empty():
			continue
		elif not info["is_through"]:
			cost = -1
		cost = info["cost"]
	
	return cost




## 获取 cell 信息
func get_tileset_cell_info(_tileset: TileSet, _id: int, _cell: Vector2) -> Dictionary:
	return _tileset.get_cell_info(_id, _cell)




## 回调寻路包装
## 由玩家点击 SelectManage 的移动区域时调用
func call_pathfinding(_args: Dictionary) -> bool:
	#print("call pathfinding > ", JSON.stringify(_args, "\t"))
	var path: PackedVector2Array = pathfinding(
		_args["unit"],
		_args["cost_list"] ,
		_args["target_position"]
	)
	# 获取图块详细信息
	var cells_info: Dictionary = {}
	for pos in path:
		var cells: Dictionary = get_position_all_layer_call(pos)
		for layer in cells:
			var cell: Dictionary = cells[layer]
			var info: Dictionary = get_tileset_cell_info(cell["tileset"], cell["id"], cell["position"])
			if not info.is_empty():
				cells_info[pos] = info
	# 调用移动
	_args["unit"].action.move_conduct(path, cells_info)
	return true




## 寻路，返回一条路径路径
func pathfinding(_unit: Unit, _cost: Dictionary, _target: Vector2) -> PackedVector2Array:
	var start_point: int = get_point_id(local_to_map(_unit.position))
	var target_point: int = get_point_id(local_to_map(_target))
	# A*算法支持
	var astart: AStar2D = AStar2D.new()
	astart.reserve_space(_cost.size())
	# 点的 id，以地图坐标为 key，id 为 value
	var point_id_list: Dictionary = {}
	
	# 添加点
	for key in _cost:
		# 转换坐标为地图坐标
		var map_point: Vector2 = local_to_map(key)
		point_id_list[map_point] = get_point_id(map_point)
		# 添加点
		astart.add_point(point_id_list[map_point], map_point, _cost[key])
	
	var directions: PackedVector2Array = [
		Vector2.UP,
		Vector2.LEFT,
		Vector2.DOWN,
		Vector2.RIGHT
	]
	
	# 连接点
	# 需要遍历点
	# 然后获取上下左右的位置并判断点是否存在
	for map_point in point_id_list:
		for direction in directions:
			var adjacent: Vector2 = map_point + direction
			# 如果这个相邻点存在，就连接它们
			if point_id_list.has(adjacent):
				astart.connect_points(point_id_list[map_point], point_id_list[adjacent])
	
	# 查询路径，获取 id
	var path_id: PackedInt64Array = astart.get_id_path(start_point, target_point)
	var path_position: PackedVector2Array = []
	
	# 转换地图坐标为场景坐标
	for id in path_id:
		path_position.append(map_to_local(astart.get_point_position(id)))
	
	return path_position




## 获取点的id
## 用这个方法的图块必须在 (0, 0) 以上
func get_point_id(_point: Vector2) -> int:
	return _point.x * 10 + _point.y




func get_tile_size() -> Vector2:
	return tile_set.tile_size
